import {
  createSketion,
  SketionHttp,
  SketionConfig,
  SketionRequestOptions,
  RequestTaskType,
} from "../../sketion_http/index";
import { Notify, Toast } from "vant";
import axios, { AxiosRequestConfig, AxiosInstance, AxiosResponse } from "axios";
import qs from "qs";
import { CachePool } from "./cache";

export interface MyRequest extends SketionRequestOptions, AxiosRequestConfig {
  toastToken?: any;
  loadingText?: string;
  showLoading?: boolean;
  needCache?: boolean;
}

let sketionUtil: SketionHttp<MyRequest, MyResponse>;

let myAxios: AxiosInstance;

export function copyNewRes(res: MyResponse): MyResponse {
  return new MyResponse(res.code, res.msg, res.data, res._originalData_);
}

export class MyResponse<T = any> {
  public code: number;

  public msg: string;

  public data: T;

  public _originalData_: any;

  constructor(code: number, msg: string, data: T, originalData: any) {
    this.code = code;
    this.msg = msg;
    this.data = data;
    this._originalData_ = originalData;
  }

  public get isLoading() {
    return this.code === -100;
  }

  public get success() {
    return this.code === 0;
  }

  public setEmpty(): MyResponse<T> {
    this.data = null as any;
    return this;
  }

  public setError(err: string): MyResponse<T> {
    this.code = 500;
    this.msg = err;
    return this;
  }

  public setLoading(data?: any): MyResponse<T> {
    this.code = -100;
    this.data = data;
    return this;
  }

  public setSuccess(data?: any): MyResponse<T> {
    this.code = 0;
    this.data = data;
    return this;
  }

  public update(newRes: MyResponse<T>): MyResponse<T> {
    const newMyRes = newRes as MyResponse<T>;
    this.code = newMyRes.code;
    this.data = newMyRes.data;
    this.msg = newMyRes.msg;
    this._originalData_ = newMyRes._originalData_;
    return this;
  }
}

const MyHttpConfig: SketionConfig<MyRequest, MyResponse> = {
  getDataFromCache: (request) => {
    const { needCache = false } = request;

    if (!needCache) {
      return null;
    }
    return CachePool.getInstance().getCache(request);
  },
  beforeRequest: (request) => {
    if (request && request.showLoading)
      Toast.loading({
        message: request?.loadingText || "加载中...",
        forbidClick: true,
        duration: 0,
      });
  },
  afterRequest: (response, request) => {
    console.log("--afterRequest--", response);

    if (request && request.toastToken) {
      request?.toastToken.close();
      Toast.clear();
    } else {
      Toast.clear();
    }

    Toast.clear();
    if (!response.success) {
      Notify({ type: "warning", message: response.msg });
    }

    return response;
  },
  sendRequest(request) {
    return myAxios(request as MyRequest);
  },
  parseRes(res: any) {
    const axiosRes = res as AxiosResponse;
    if (axiosRes.status === 200) {
      if (axiosRes.data) {
        return Promise.resolve(
          new MyResponse(
            axiosRes.data.code,
            axiosRes.data.msg,
            axiosRes.data.data,
            axiosRes
          )
        );
      } else {
        return new MyResponse(500, "res.data is null", null, axiosRes);
      }
    } else {
      return new MyResponse(res.status, res.statusText, null, axiosRes);
    }
  },
  parseError(error: Error) {
    return new MyResponse(500, error.message, null, error);
  },
};

export function initHttpHooks() {
  const baseUrl = process.env.VUE_APP_SERVER;

  console.log("-----baseUrl--------", baseUrl);

  myAxios = axios.create({
    baseURL: baseUrl,
    timeout: 2000,
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "x-sychapi-sessionid": "57f7cc4e-502b-46ac-a442-ee38f283a1fe",
    },
    transformRequest: [
      function(data, headers) {
        // 对 data 进行任意转换处理
        if (data) {
          data.userid = "123123";
        }
        console.log("----transformRequest----", data);
        return qs.stringify(data);
      },
    ],
  });
  sketionUtil = createSketion(MyHttpConfig);
}

export function sendMyHttpRequest<T>(
  request: MyRequest
): Promise<MyResponse<T>> {
  return sketionUtil.sendRequest(request);
}

export function embraceRequest<T>(
  request: RequestTaskType,
  opts?: SketionRequestOptions
): Promise<MyResponse<T>> {
  return sketionUtil.embraceRequest(request, opts);
}

export function createLoadingRes<T>(data?: any): MyResponse<T> {
  return new MyResponse<T>(-100, "", data, null);
}
